
#include "stdafx.h"
#include "Header.h"

#include <ctime>

	namespace las
	{
		Header::Header()
		{
			Init();
		}

		Header::Header(const Header &h)
		{
			*this = h;
		}
		
		Header& Header::operator=(const Header& h)
		{
			m_VersionMajor = h.m_VersionMajor;
			m_VersionMinor = h.m_VersionMinor;
			return *this;
		}

		void Header::Init()
		{
			m_VersionMajor = 1;
			m_VersionMinor = 4;

			m_CreateDOY = m_CreateYear = 0;
			std::time_t now;
			std::time(&now);
			std::tm* ptm = std::gmtime(&now);
			if (0 != ptm)
			{
				m_CreateDOY = static_cast<uint16_t>(ptm->tm_yday);
				m_CreateYear = static_cast<uint16_t>(ptm->tm_year + 1900);
			}

			m_HeaderSize = 343;
			
			m_SourceId = 0;
			m_GlobalEncoding = 0;
			m_ProjectId1 = 0;
			m_ProjectId2 = 0;
			m_ProjectId3 = 0;
			std::memset(m_ProjectId4, 0, 8);

			m_DataOffset = m_HeaderSize;
			m_RecordsCount = 0;
			m_PointRecordsCount = 0;

			memcpy_s(m_Signature, 4, "LASF", 4);

			memset(m_SystemId, 0, 32);
			memcpy_s(m_SystemId, 32, "AdzukiLas", 9);

			memset(m_SystemId, 0, 32);
			memcpy_s(m_SystemId, 32, "AdzukiLas 0.1", 13);
		
			memset(m_PointRecordsByReturn, 0, 120);

			SetScale(0.001, 0.001, 0.001);
			SetOffset(0, 0, 0);

			m_StartOfWaveform = 0;
		}

		Header::~Header()
		{

		}

		std::string Header::GetFileSignature() const
		{
			return std::string(m_Signature, 4);
		}

		void Header::SetFileSignature( std::string const& value )
		{
// 			if (0 != v.compare(0, eFileSignatureSize, FileSignature))
// 				throw std::invalid_argument("invalid file signature");
			memcpy_s(m_Signature, 4, value.c_str(), 4);
		}

		std::uint16_t Header::GetSourceID() const
		{
			return m_SourceId;
		}

		void Header::SetSourceID( std::uint16_t value )
		{
			m_SourceId = value;
		}

		std::uint16_t Header::GetGlobalEncoding() const
		{
			return m_GlobalEncoding;
		}

		void Header::SetGlobalEncoding( std::uint16_t value )
		{
			m_GlobalEncoding = value;
		}

		GUID Header::GetProjectID() const
		{
			GUID guid;
			guid.Data1 = m_ProjectId1;
			guid.Data2 = m_ProjectId2;
			guid.Data3 = m_ProjectId3;
			memcpy_s(guid.Data4, 8, m_ProjectId4, 8);
			return guid;
		}

		void Header::SetProjectID( GUID const &value )
		{
			m_ProjectId1 = value.Data1;
			m_ProjectId2 = value.Data2;
			m_ProjectId3 = value.Data3;
			memcpy_s(m_ProjectId4, 8, value.Data4, 8);
		}

		std::uint8_t Header::GetVersionMajor() const
		{
			return m_VersionMajor;
		}

		void Header::SetVersionMajor( std::uint8_t value )
		{
			m_VersionMajor = value;
		}

		std::uint8_t Header::GetVersionMinor() const
		{
			return m_VersionMinor;
		}

		void Header::SetVersionMinor( std::uint8_t value )
		{
			m_VersionMinor = value;
		}

		std::string Header::GetSystemID() const
		{
			return std::string(std::string(m_SystemId, 32).c_str());
		}

		void Header::SetSystemID( std::string const &value )
		{
			memset(m_SystemId, 0, 32);
			memcpy_s(m_SystemId, 32, value.c_str(), 32);
		}

		std::string Header::GetSoftwareID() const
		{
			return std::string(std::string(m_SoftwareId, 32).c_str());
		}

		void Header::SetSoftwareID( std::string const &value )
		{
			memset(m_SoftwareId, 0, 32);
			memcpy_s(m_SoftwareId, 32, value.c_str(), 32);
		}

		std::uint16_t Header::GetCreatDOY() const
		{
			return m_CreateDOY;
		}

		void Header::SetCreateDOY( std::uint16_t value )
		{
			m_CreateDOY = value;
		}

		std::uint16_t Header::GetCreateYear() const
		{
			return m_CreateYear;
		}

		void Header::SetCreateYear( std::uint16_t value )
		{
			m_CreateYear = value;
		}

		std::uint16_t Header::GetHeaderSize() const
		{
			return m_HeaderSize;
		}

		void Header::SetHeaderSize( std::uint16_t value )
		{
			m_HeaderSize = value;
		}

		std::uint64_t Header::GetDataOffset() const
		{
			return m_DataOffset;
		}

		void Header::SetDataOffset( std::uint64_t value )
		{
			m_DataOffset = value;
		}

		std::uint32_t Header::GetRecordCount() const
		{
			return m_RecordsCount;
		}

		void Header::SetRecordCount( std::uint32_t value )
		{
			m_RecordsCount = value;
		}

		std::uint8_t Header::GetPointFormat() const
		{
			return m_PointFormat;
		}

		void Header::SetPointFormat( std::uint8_t value )
		{
			m_PointFormat = value;
			switch(m_PointFormat)
			{
			case 0:
				m_PointRecordLength = 20;
				break;
			case 1:
				m_PointRecordLength = 28;
				break;
			case 2:
				m_PointRecordLength = 26;
				break;
			case 3:
				m_PointRecordLength = 34;
				break;
			case 4:
				m_PointRecordLength = 57;
				break;
			case 5:
				m_PointRecordLength = 63;
				break;
			case 6:
				m_PointRecordLength = 30;
				break;
			case 7:
				m_PointRecordLength = 36;
				break;
			case 8:
				m_PointRecordLength = 38;
				break;
			case 9:
				m_PointRecordLength = 58;
				break;
			case 10:
				m_PointRecordLength = 67;
				break;
			default:
				m_PointRecordLength = 0;
			}
		}

		std::uint16_t Header::GetPointRecordLength() const
		{
			return m_PointRecordLength;
		}

		std::uint64_t Header::GetPointRecordsCount() const
		{
			return m_PointRecordsCount;
		}

		void Header::SetPointRecordsCount( std::uint64_t value )
		{
			m_PointRecordsCount = value;
		}

		std::uint64_t* Header::GetPointRecordsByReturn() const
		{
			return (std::uint64_t*)m_PointRecordsByReturn;
		}

		void Header::SetPointRecordsByReturn( std::size_t index, std::uint64_t value )
		{
			m_PointRecordsByReturn[index] = value;
		}

		double Header::GetScaleX() const
		{
			return m_Scales[0];
		}

		double Header::GetScaleY() const
		{
			return m_Scales[1];
		}

		double Header::GetScaleZ() const
		{
			return m_Scales[2];
		}

		void Header::SetScale( double x, double y, double z )
		{
			m_Scales[0] = x;
			m_Scales[1] = y;
			m_Scales[2] = z;
		}

		double Header::GetOffsetX() const
		{
			return m_Offsets[0];
		}

		double Header::GetOffsetY() const
		{
			return m_Offsets[1];
		}

		double Header::GetOffsetZ() const
		{
			return m_Offsets[2];
		}

		void Header::SetOffset( double x, double y, double z )
		{
			m_Offsets[0] = x;
			m_Offsets[1] = y;
			m_Offsets[2] = z;
		}

		double Header::GetMaxX() const
		{
			return m_Extent[0];
		}

		double Header::GetMinX() const
		{
			return m_Extent[1];
		}

		double Header::GetMaxY() const
		{
			return m_Extent[2];
		}

		double Header::GetMinY() const
		{
			return m_Extent[3];
		}

		double Header::GetMaxZ() const
		{
			return m_Extent[4];
		}

		double Header::GetMinZ() const
		{
			return m_Extent[5];
		}

		void Header::SetMax( double x, double y, double z )
		{
			m_Extent[0] = x;
			m_Extent[2] = y;
			m_Extent[4] = z;
		}

		void Header::SetMin( double x, double y, double z )
		{
			m_Extent[1] = x;
			m_Extent[3] = y;
			m_Extent[5] = z;
		}

		std::uint64_t Header::GetStartOfWaveform() const
		{
			return m_StartOfWaveform;
		}

		void Header::SetStartOfWaveform( std::uint64_t value )
		{
			m_StartOfWaveform = value;
		}
	}